package edu.mapi.ir.controllers.reactive;

import java.util.Vector;

import edu.mapi.ir.ciberIF.ciberIF;

/**
 * This Controller implements the subsumption paradigm by basing its decisions in a list of controllers.
 * Following a restrict order, each descendant controller accesses the current robot state and verifies if 
 * it can be applied. If the controller can't be applied, then tries to apply the next controller and so on.
 * @author ZP
 */
public class SubsumptionController implements ReactiveController {

	private Vector<ReactiveController> controllers = new Vector<ReactiveController>();
	private ReactiveController decisiveController = null;
	private int beaconToFollow = 0;
	
	/**
	 * Adds a controller to the end of the list of controllers
	 * @param controller The controller to be added
	 */
	public void addController(ReactiveController controller) {
		if (!controllers.contains(controller))
			controllers.add(controller);
	}
	
	/**
	 * Remove the given controller from the list of controllers
	 * @param controller The controller to be removed
	 * @return <b>true</b> if the controller was removed or <b>false</b> if the controller was not found
	 */
	public boolean removeController(ReactiveController controller) {
		return controllers.remove(controller);
	}
	
	/**
	 * This method makes a decision based on the decision of one of its descendant controllers 
	 * (following an subsumption paradigm)
	 * @param cif The cibermouse interface object
	 * @return <b>true</b> if this controller was applied successfully or <b>false</b> 
	 * if this controller could not be applied to the current robot state
	 */
	public boolean decide(ciberIF cif) {
		
		cif.RequestIRSensor(0);
		cif.RequestIRSensor(1);
		cif.RequestIRSensor(2);
		if(cif.GetTime() % 2 == 0) 
			cif.RequestGroundSensor();
		else cif.RequestBeaconSensor(beaconToFollow);
		
		for (ReactiveController c : controllers) {
			if (c.decide(cif)) {
				decisiveController = c;				
				return true;
			}		
		}
		
		decisiveController = this;
		return false;
	}
	
	public String getDescription() {
		return "Subsumption Controller";
	}

	/**
	 * @return The controller that was used to make the last decision 
	 */
	public ReactiveController getDecisiveController() {
		return decisiveController;
	}
	
	public String[] getControllerNames() {
		String[] names = new String[controllers.size()];
		for (int i = 0; i < controllers.size(); i++)
			names[i] = controllers.get(i).getDescription();
		
		return names;
	}
}
